Show all ACP runtimes with install status and one-click install#724
Merged
Conversation
tlongwell-block
approved these changes
May 22, 2026
ab8ef0c to
2387b97
Compare
…buttons The "Preferred runtime" dropdown in Agents > Add Persona and the Doctor panel only showed runtimes with a resolved ACP adapter binary, silently hiding Claude Code and Codex when their adapters weren't installed. Add three-state availability detection (Available / AdapterMissing / NotInstalled) to distinguish "CLI present but adapter missing" from "nothing installed." Expose a full provider catalog via `discover_all_acp_providers` and an `install_acp_runtime` command that runs server-defined install scripts in a login shell with a 5-minute timeout. Doctor panel now shows all four known runtimes with status badges and Install buttons. PersonaDialog shows all runtimes with status labels so users can store a preference for later. CreateAgentDialog shows a hint when additional runtimes are available to install.
…iew findings The original implementation created a second parallel Tauri command (discover_all_acp_providers) alongside the existing one to avoid changing the return type. This produced two commands, two hooks, two query keys, and two raw type converters. Consolidates into a single command returning the full catalog, with a useAvailableAcpProviders hook that type-narrows for callers needing non-null command/binaryPath. Also fixes: pipe deadlock in install command (#1), UTF-8 truncation panic (#2/#4), adds install concurrency guard (#11), exact provider ID match (#15), error display stdout fallback (#5), success banner suppression when already available (#12), misleading re-run text (#13), IIFE refactor in PersonaDialog (#14), hidden internal query lift (#7), configurable e2e mocks (#9), shared raw type exports (#8), and classify_provider unit tests (#10).
…olidation Fix CI-breaking missing `AcpAvailabilityStatus` import in tauri.ts, eliminate zombie process leak on install timeout by saving PID before thread move and sending SIGTERM, remove duplicate Map keys in check-file-sizes.mjs that silently shadowed earlier entries, clean up dead `MockAcpProvider` type from e2eBridge, and add missing `classify_provider` test for the no-underlying-CLI code path.
…Catalog field
The onboarding E2E test passed `{ acpProviders: [] }` to the mock
bridge, but the bridge handler was renamed to read
`acpProvidersCatalog` during consolidation. The stale field name was
silently ignored, causing the default catalog (with available
providers) to be returned instead of an empty list.
…rmit env leak Replace window.open() with <a target="_blank"> for "View instructions" links — Tauri blocks window.open but handles anchor tags correctly. Fix Claude Code adapter install command: the package is @agentclientprotocol/claude-agent-acp (not @anthropic-ai/claude-agent-acp which doesn't exist on npm). Strip NPM_CONFIG_PREFIX, NPM_CONFIG_CACHE, and COREPACK_HOME from the install subprocess environment so npm uses the user's normal registry rather than inheriting hermit's project-local Artifactory proxy config.
eea5054 to
f1821bc
Compare
Tauri does not open external URLs via <a target="_blank"> — the click is silently swallowed. Use openUrl() from @tauri-apps/plugin-opener which correctly dispatches to the system default browser.
Goose has native ACP support (no separate adapter), so the install script belongs in cli_install_commands, not adapter_install_commands. Also sets underlying_cli to "goose" since the CLI binary exists. Codex ACP adapter is available on npm as @zed-industries/codex-acp — enable auto-install and point docs link to the actual adapter repo instead of the main Codex repo.
…, dynamic install hints Re-run button now clears the binary resolve cache so it actually re-probes the filesystem instead of returning stale cached results. Replace global AtomicBool install guard with per-provider Mutex<HashSet<String>> so concurrent installs for different providers (e.g. claude + codex) can proceed in parallel. Add codex CLI install command (npm install -g @openai/codex) so clicking Install when both CLI and adapter are missing installs both. Compute install_hint dynamically based on availability state so the UI accurately describes what the Install button will do.
When the ACP adapter binary is found but the underlying CLI is missing (e.g. codex-acp installed without codex), classify_provider now returns CliMissing instead of Available. The adapter can't function without the CLI, so Doctor shows an amber warning with an Install button that will set up the missing CLI.
@openai/codex on npm uses platform-specific sub-packages and the latest alpha publishes only a win32-x64 variant, causing EBADPLATFORM on macOS. Switch to the official install script which handles platform detection.
Claude Code is now a Rust binary with platform-specific npm packaging. Their docs recommend the native install script over npm. Switch to curl -fsSL https://claude.ai/install.sh | bash.
…er_install_hint The single install_hint field was semantically ambiguous — it referred to the CLI for some providers and the adapter for others. Split into two fields so each provider clearly describes both install steps. The dynamic hint composition in discover_acp_providers selects the right hint based on availability state: CliMissing shows the CLI hint, AdapterMissing shows the adapter hint, NotInstalled shows both.
Rename section header to "Agent CLIs and ACP runtimes" with a descriptive subheader. Show both CLI and ACP adapter paths when a provider has a separate adapter (Claude Code, Codex). Add "ACP support built-in" note for providers with native ACP (Goose, Sprout Agent).
…tive hangs Install commands like the Codex CLI script prompt "Start Codex now? [y/N]" which blocks forever when the subprocess inherits stdin from the Tauri process. Redirect stdin from /dev/null so any interactive prompt gets an immediate EOF and defaults to its non-interactive behavior.
Install scripts like Codex's install.sh explicitly open /dev/tty to
prompt interactively ("Start Codex now? [y/N]"), bypassing our
stdin(Stdio::null()). Call setsid() in pre_exec to create a new
session without a controlling terminal, forcing the script's fallback
to read from stdin (/dev/null → EOF → default answer).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
discover_local_acp_providers()silently filtered out any runtime whose ACP adapter binary wasn't on disk, hiding Claude Code and Codex even when the user had the underlying CLI installed. There was no indication these runtimes existed or how to enable them.discover_acp_providers()that returns all known runtimes regardless of install stateinstall_acp_runtimeTauri command with two-phase install (CLI then adapter), login shell execution,stdin(Stdio::null())to prevent interactive prompts from hanging, 5-minute timeout with PID-basedSIGTERM, and per-provider concurrency guard viaMutex<HashSet<String>>discover_acp_providerscall so the Re-run button in Doctor actually re-probes the filesysteminstall_hintintocli_install_hintandadapter_install_hintper provider; compose the appropriate hint dynamically indiscover_acp_providers()based on availability stateopenUrl()from@tauri-apps/plugin-openerfor external links (Tauri silently swallowswindow.open()and<a target="_blank">)download_cli.sh), Claude Code (claude.ai/install.sh), Codex (chatgpt.com/codex/install.sh); npm for ACP adapters (@agentclientprotocol/claude-agent-acp,@zed-industries/codex-acp)underlying_cliset to"goose"with install incli_install_commands(native ACP, no adapter), Codex docs link tozed-industries/codex-acp, Claude Code adapter@agentclientprotocol/claude-agent-acpNPM_CONFIG_PREFIX,NPM_CONFIG_CACHE,COREPACK_HOME) in install subprocesses so npm uses the user's normal registryAcpProvideras a narrowed intersection type ofAcpProviderCatalogEntrywithuseAvailableAcpProviders()hook for callers that need non-nullcommand/binaryPath, preservingChannelAgentProviderand all downstream callers unchangedclassify_provider()with 5 unit tests covering all four states plus the no-underlying-CLI path; consolidated E2E bridge mocks with configurable overridesReplaces #715 (branch rename).